package com.server.util;

import java.io.FileNotFoundException;
import java.io.FileOutputStream;
import java.io.IOException;
import java.lang.reflect.Field;
import java.util.ArrayList;
import java.util.List;

import javax.xml.parsers.DocumentBuilderFactory;
import javax.xml.parsers.ParserConfigurationException;
import javax.xml.transform.OutputKeys;
import javax.xml.transform.Transformer;
import javax.xml.transform.TransformerConfigurationException;
import javax.xml.transform.TransformerException;
import javax.xml.transform.TransformerFactory;
import javax.xml.transform.dom.DOMSource;
import javax.xml.transform.stream.StreamResult;

import org.w3c.dom.Attr;
import org.w3c.dom.DOMException;
import org.w3c.dom.Document;
import org.w3c.dom.Element;
import org.w3c.dom.Node;
import org.w3c.dom.NodeList;
import org.w3c.dom.Text;
import org.xml.sax.SAXException;

import com.bean.Product;

public class XmlParseHelper {

	public static <T> List<T> getAll(String xml, Class<T> clazz) {
		List<T> retList = new ArrayList<>();
		String tagName = clazz.getSimpleName();
		try {
			NodeList nodeList = getElements(xml, tagName);
			int length = nodeList.getLength();
			for (int i = 0; i < length; i++) {
				T t = clazz.newInstance();
				Node item = nodeList.item(i);
				Node attrNode = item.getAttributes().getNamedItem("id");
				if(attrNode != null) {
					Field f = clazz.getDeclaredField("id");
					f.setAccessible(true);
					f.set(t, attrNode.getTextContent());
				}
				NodeList childNodes = item.getChildNodes();
				for (int j = 0; j < childNodes.getLength(); j++) {
					Node childItem = childNodes.item(j);
					String textContent = childItem.getTextContent();
					Field[] fields = clazz.getDeclaredFields();
					for (Field field : fields) {
						field.setAccessible(true);
						if(field.getName().equals(childItem.getNodeName())) {
							field.set(t, textContent);
						}
					}
				}
				retList.add(t);
			}
		} catch (IllegalArgumentException e) {
			e.printStackTrace();
		} catch (IllegalAccessException e) {
			e.printStackTrace();
		} catch (DOMException e) {
			e.printStackTrace();
		} catch (InstantiationException e) {
			e.printStackTrace();
		} catch (NoSuchFieldException e) {
			e.printStackTrace();
		} catch (SecurityException e) {
			e.printStackTrace();
		}
		return retList;
	}
	
	public static void updataQuantity(String xml, Product product) {
		Document document = getDocument(xml);
		NodeList nodeList = document.getElementsByTagName("Product");
		for (int i = 0; i < nodeList.getLength(); i++) {
			Node item = nodeList.item(i);
			Element element = (Element) item;
			String ids = element.getAttribute("id");
			if(product.getId().equals(ids)) {
				System.out.println(ids);
				NodeList childNodes = item.getChildNodes();
				for(int j = 0; j < childNodes.getLength(); j++) {
					Node childItem = childNodes.item(j);
					if(childItem.getNodeName().equals("quantity")) {
						childItem.setTextContent(product.getQuantity());
						System.out.println(childItem.getTextContent());
						saveXml(document, xml);
						break;
					}
				}
			}
		}
	}
	
	public static <T> void addNode(String xml, T t) {
		Document document = getDocument(xml);
		Element rootDocument = document.getDocumentElement();
		Element productEle = document.createElement(t.getClass()
				.getSimpleName());
		Field[] feilds = t.getClass().getDeclaredFields();
		for (Field f : feilds) {
			f.setAccessible(true);
			try {
				if (!f.getName().equals("serialVersionUID")) {
					if (f.getName().equals("id")) {
						Attr attr = document.createAttribute("id");
						attr.setValue(f.get(t).toString());
						productEle.setAttributeNode(attr);
					} else {
						Element childEle = document.createElement(f.getName());
						Text nodeText = document.createTextNode(f.get(t).toString());
						childEle.appendChild(nodeText);
						productEle.appendChild(childEle);
					}
				}
			} catch (IllegalArgumentException e) {
				e.printStackTrace();
			} catch (IllegalAccessException e) {
				e.printStackTrace();
			}
		}
		rootDocument.appendChild(productEle);
		saveXml(document, xml);
	}
	
	private static void saveXml(Document document, String xml) {
		TransformerFactory factory = TransformerFactory.newInstance();
		try {
			Transformer transformer = factory.newTransformer();
			DOMSource domSource = new DOMSource(document);
			transformer.setOutputProperty(OutputKeys.ENCODING, "UTF-8");
			StreamResult result = new StreamResult(new FileOutputStream(xml));
			transformer.transform(domSource, result);
		} catch (TransformerConfigurationException e) {
			e.printStackTrace();
		} catch (FileNotFoundException e) {
			e.printStackTrace();
		} catch (TransformerException e) {
			e.printStackTrace();
		}
	}
	
	private static NodeList getElements(String xml, String tagName) {
		NodeList nodeList = getDocument(xml).getElementsByTagName(tagName);
		return nodeList;
	}
	
	private static Document getDocument(String xml) {
		Document document = null;
		try {
			document = DocumentBuilderFactory.newInstance()
					.newDocumentBuilder().parse(xml);
		} catch (SAXException e) {
			e.printStackTrace();
		} catch (IOException e) {
			e.printStackTrace();
		} catch (ParserConfigurationException e) {
			e.printStackTrace();
		}
		return document;
	}
	
	public static void test(String xml) {
		Document document = getDocument(xml);
		NodeList nodeList = document.getElementsByTagName("Product");
		for (int i = 0; i < nodeList.getLength(); i++) {
			Node item = nodeList.item(i);
			String ids = item.getAttributes().getNamedItem("id").getTextContent();
			if("1001".equals(ids)) {
				System.out.println(ids);
			}
		}
		/*Node item = nodeList.item(1);
		System.out.println(item.getNodeName() + ":" + item.getNodeType());
		System.out.println(item.getAttributes());
		Node namedItem = item.getAttributes().getNamedItem("id");
		System.out.println(namedItem.getTextContent());*/
	}
	
}
